Skip to content

Add in-process FFI transport for Rust SDK#1915

Merged
SteveSandersonMS merged 15 commits into
mainfrom
stevesa/ffi-inproc-rust-ts
Jul 10, 2026
Merged

Add in-process FFI transport for Rust SDK#1915
SteveSandersonMS merged 15 commits into
mainfrom
stevesa/ffi-inproc-rust-ts

Conversation

@SteveSandersonMS

@SteveSandersonMS SteveSandersonMS commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds an in-process transport to the Rust SDK so it can host the Copilot runtime cdylib directly instead of spawning a CLI subprocess. The transport continues to use the existing LSP-framed JSON-RPC connection over the runtime C ABI.

Changes

  • Adds Transport::InProcess and supports selecting it with COPILOT_SDK_DEFAULT_CONNECTION=inprocess.
  • Loads the runtime library once per process and bridges its connection callbacks to Rust AsyncRead/AsyncWrite streams.
  • Discovers or extracts the platform runtime.node library alongside the embedded CLI, including platform-specific library naming.
  • Starts the in-process worker in the configured client working directory and aligns its authentication environment with the E2E proxy.
  • Adds in-process E2E coverage and Linux/macOS CI jobs.
  • Skips BYOK scenarios that require multiple process-wide inference providers, which the in-process runtime does not support.

Backward compatibility

The existing out-of-process (stdio/tcp) transports remain source-compatible — no breaking changes for current consumers:

  • Transport::Stdio stays a unit variant and Transport::Tcp keeps { port, connection_token } (no per-transport env field).
  • ClientOptions::working_directory stays PathBuf (an empty path means "unset" and resolves to the process cwd at start()).
  • ClientOptions::env/env_remove (and with_env/with_env_remove) remain non-deprecated; they still apply to the child process for stdio/tcp and are rejected for Transport::InProcess.

Transport::Default, Transport::InProcess, and COPILOT_SDK_DEFAULT_CONNECTION are additive.

Scope

This PR now contains only Rust SDK changes plus the Rust SDK test workflow. The TypeScript/Node implementation was removed because it merged separately.

Comment thread .github/workflows/rust-sdk-tests.yml Fixed
Comment thread .github/workflows/rust-sdk-tests.yml Fixed
Comment thread rust/src/ffi.rs Fixed
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@SteveSandersonMS SteveSandersonMS force-pushed the stevesa/ffi-inproc-rust-ts branch from 9587efd to 259911f Compare July 7, 2026 13:49
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generated by SDK Consistency Review Agent for issue #1915 · sonnet46 2M

Comment thread nodejs/src/types.ts
@github-actions

This comment has been minimized.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generated by SDK Consistency Review Agent for issue #1915 · sonnet46 2.4M

Comment thread nodejs/src/client.ts
Comment thread rust/src/lib.rs Outdated
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generated by SDK Consistency Review Agent for issue #1915 · sonnet46 2M

Comments that could not be inline-anchored

nodejs/src/client.ts:639

Cross-SDK consistency: missing eager validation for inprocess + incompatible options

The .NET SDK (reference implementation since #1901) throws an ArgumentException in the constructor when Environment or Telemetry options are set alongside InProcessRuntimeConnection — see Client.cs ValidateEnvironmentOptions(). The new TypeScript implementation only documents the limitation in JSDoc but silently ignores those options, which can be confusing.

Suggest adding a "fail fast" chec…

rust/src/lib.rs:1012

Cross-SDK consistency: missing eager validation for Transport::InProcess + incompatible options

The .NET SDK (reference since #1901) rejects incompatible options early with ArgumentException. The TypeScript implementation (also added in this PR) has the same gap. For Rust, suggest adding a validation block after the External checks, mirroring the pattern here:

if matches!(options.transport, Transport::InProcess) {
    if options.github_token.is_some() {
        return Err(Er…

</details>

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@SteveSandersonMS SteveSandersonMS force-pushed the stevesa/ffi-inproc-rust-ts branch from 6b989d4 to b1576e0 Compare July 9, 2026 14:55
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Cross-SDK Consistency Review

This PR ports the in-process FFI transport from .NET (#1901) to TypeScript and Rust. Here's how the implementations compare.

✅ API naming — consistent across the three SDKs

SDK Transport selection Factory / variant
.NET RuntimeConnection.ForInProcess() InProcessRuntimeConnection class
TypeScript RuntimeConnection.forInProcess() InProcessRuntimeConnection interface
Rust Transport::InProcess enum variant

COPILOT_SDK_DEFAULT_CONNECTION env-var override is implemented consistently in all three SDKs with the same accepted values (inprocess / stdio / unset) and the same error on any other value. ✅

⚠️ One consistency gap: missing fail-fast validation for per-client options

The .NET SDK throws ArgumentException at construction time if Environment or Telemetry are set alongside RuntimeConnection.ForInProcess() (see ValidateEnvironmentOptions in Client.cs). This gives callers an early, actionable error rather than silently ignoring the config.

Neither the TypeScript nor the Rust SDK currently validate this. A caller who passes gitHubToken / telemetry / env with the in-process transport will see those values silently dropped, which can be hard to debug (especially gitHubToken — auth appearing not to work with no error message).

I've left inline suggestions on the specific lines in nodejs/src/client.ts and rust/src/lib.rs where this validation could be added to match .NET behaviour.

i️ Python, Go, Java — expected gap

None of the three remaining SDKs implement in-process FFI transport yet, and none handle COPILOT_SDK_DEFAULT_CONNECTION. This is an expected gap for a multi-PR rollout (no action needed in this PR), but worth tracking so it doesn't stay inconsistent long-term once the feature graduates from experimental.

Generated by SDK Consistency Review Agent for issue #1915 · sonnet46 2M ·

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generated by SDK Consistency Review Agent for issue #1915 · sonnet46 2M

Comment thread nodejs/src/client.ts
Comment thread rust/src/lib.rs
@SteveSandersonMS SteveSandersonMS force-pushed the stevesa/ffi-inproc-rust-ts branch from b1576e0 to cc686bb Compare July 10, 2026 09:42
@SteveSandersonMS SteveSandersonMS changed the title Add in-process FFI transport for Rust and TypeScript SDKs Add in-process FFI transport for Rust SDK Jul 10, 2026
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: da0a9335-969e-4a77-838a-daac9206a454
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: da0a9335-969e-4a77-838a-daac9206a454
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: da0a9335-969e-4a77-838a-daac9206a454
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: da0a9335-969e-4a77-838a-daac9206a454
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: da0a9335-969e-4a77-838a-daac9206a454
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: da0a9335-969e-4a77-838a-daac9206a454
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: da0a9335-969e-4a77-838a-daac9206a454
@SteveSandersonMS SteveSandersonMS force-pushed the stevesa/ffi-inproc-rust-ts branch from 441f78c to 4d480b4 Compare July 10, 2026 12:34
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: da0a9335-969e-4a77-838a-daac9206a454
Comment thread rust/build/in_process.rs Fixed
Comment thread rust/build/out_of_process.rs Fixed
@SteveSandersonMS SteveSandersonMS marked this pull request as ready for review July 10, 2026 12:54
@SteveSandersonMS SteveSandersonMS requested a review from a team as a code owner July 10, 2026 12:54
Copilot AI review requested due to automatic review settings July 10, 2026 12:54
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: da0a9335-969e-4a77-838a-daac9206a454
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: da0a9335-969e-4a77-838a-daac9206a454

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an in-process (FFI) transport option to the Rust SDK so it can host the Copilot runtime cdylib directly (no CLI subprocess), while updating bundling/pinning to include the native runtime library and expanding CI/E2E coverage for the new transport.

Changes:

  • Introduces Transport::{Default, Stdio{env}, InProcess, Tcp{env}, External} and updates Client::start/option validation to support env-driven default transport selection and in-process hosting behind bundled-in-process.
  • Adds a Rust FFI host (rust/src/ffi.rs) that loads/binds the runtime library once per process and bridges the runtime connection to AsyncRead/AsyncWrite.
  • Updates Rust E2E harness/tests, docs, build/publish scripts, and CI workflows to exercise in-process mode and to bundle/verify the runtime library alongside the embedded CLI.
Show a summary per file
File Description
rust/tests/integration_test.rs Updates test options to reflect working_directory: Option<PathBuf> API change.
rust/tests/e2e/telemetry.rs Skips telemetry test under in-process transport due to per-client env limitations.
rust/tests/e2e/support.rs Adds in-process env mirroring guard, default user setup, in-process client starter, and serializes E2E concurrency for in-process runs.
rust/tests/e2e/subagent_hooks.rs Skips sub-agent hook test in-process due to process-global inference provider limitations.
rust/tests/e2e/session_config.rs Skips specific in-process-incompatible scenario; updates TCP transport struct usage.
rust/tests/e2e/rpc_workspace_checkpoints.rs Skips in-process case where native checkpoint decoding rejects the test sentinel.
rust/tests/e2e/rpc_session_state_extras.rs Switches to helper that applies GitHub token appropriately for in-process.
rust/tests/e2e/rpc_server.rs Switches to helper that applies GitHub token appropriately for in-process.
rust/tests/e2e/provider_endpoint.rs Adjusts env gating behavior for in-process and updates token configuration helper usage.
rust/tests/e2e/per_session_auth.rs Skips in-process scenarios that depend on unsupported client-level tokens; adjusts unauthenticated case.
rust/tests/e2e/pending_work_resume.rs Updates TCP transport struct usage.
rust/tests/e2e/multi_client.rs Updates TCP transport struct usage.
rust/tests/e2e/multi_client_commands_elicitation.rs Updates TCP transport struct usage.
rust/tests/e2e/inprocess.rs Adds a basic in-process E2E smoke test (ping/status/stop).
rust/tests/e2e/copilot_request_handler.rs Skips handler-driven tests in-process due to process-global provider slot semantics.
rust/tests/e2e/client.rs Updates TCP transport struct usage and token configuration helper usage.
rust/tests/e2e/client_options.rs Updates transport usage to new Stdio { env: None } form.
rust/tests/e2e/byok_bearer_token_provider.rs Skips BYOK provider tests in-process to avoid poisoning process-global runtime state.
rust/tests/e2e.rs Registers the new in-process test module behind bundled-in-process.
rust/tests/cli_resolution_test.rs Extends pin-file validation for in-process snapshot format and asserts runtime library install when bundled-in-process.
rust/src/lib.rs Adds transport variants, option validation, transport env replacement support, and in-process client startup/teardown wiring.
rust/src/ffi.rs New Rust FFI runtime host/transport implementation using libloading and async stream adapters.
rust/src/embeddedcli.rs Extends embedded CLI installation to also extract/install the native runtime library when bundled-in-process is enabled.
rust/scripts/snapshot-bundled-in-process-version.sh Adds script to snapshot npm integrity pins for platform packages used by bundled-in-process builds.
rust/README.md Updates Rust SDK docs for transport changes and new bundled-in-process feature.
rust/Cargo.toml Adds bundled-in-process feature, includes build module sources in crate packaging, and adds libloading dependency.
rust/Cargo.lock Records libloading dependency addition.
rust/build/out_of_process.rs Refactors legacy build logic into module used when bundled-in-process is off.
rust/build/in_process.rs Adds build logic to download/verify npm package tgz and embed minimal archive with optional runtime library.
rust/build.rs Switches to selecting build implementation module based on bundled-in-process feature.
rust/.gitignore Ignores generated cli-version-in-process.txt.
.github/workflows/rust-sdk-tests.yml Adds in-process Rust E2E job (Linux/macOS), updates cache naming and clippy features.
.github/workflows/publish.yml Snapshots and verifies both CLI pin files during publish.
.github/lsp.json Removes rust-analyzer configuration from the repo LSP mapping.

Review details

  • Files reviewed: 33/34 changed files
  • Comments generated: 3
  • Review effort level: Low

Comment thread rust/src/ffi.rs
Comment thread rust/src/lib.rs Outdated
Comment thread rust/README.md Outdated
SteveSandersonMS and others added 2 commits July 10, 2026 14:03
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: da0a9335-969e-4a77-838a-daac9206a454
Reverts the source-breaking API changes the in-process transport work
introduced for existing Stdio/Tcp consumers:

- Restore `Transport::Stdio` as a unit variant and `Transport::Tcp` to
  `{ port, connection_token }` (drop the per-transport `env` field). Env
  stays on `ClientOptions::env`/`env_remove`, which still applies to the
  child process and is already rejected for `Transport::InProcess`.
- Restore `ClientOptions::working_directory` to `PathBuf` (empty = unset,
  resolved to the process cwd at start). The InProcess guard now rejects a
  non-empty working_directory.
- Un-deprecate `env`/`env_remove`/`with_env`/`with_env_remove` (their notes
  pointed at the removed transport-level env).

`Transport::Default`, `Transport::InProcess`, and COPILOT_SDK_DEFAULT_CONNECTION
are additive and unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 95ad333b-ef14-474c-9908-75ed3e21e06f
@SteveSandersonMS SteveSandersonMS merged commit bd50a9f into main Jul 10, 2026
19 checks passed
@SteveSandersonMS SteveSandersonMS deleted the stevesa/ffi-inproc-rust-ts branch July 10, 2026 14:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants